<script setup lang="ts">
  import {
    ElForm,
    ElFormItem,
    FormInstance,
    ElInput,
    ElRadioGroup,
    ElRadio,
    ElUpload,
    ElIcon,
    ElSelect,
    ElOption,
    ElTable,
    ElTableColumn,
  } from 'element-plus'
  import type { UploadFile, UploadRawFile } from 'element-plus'
  import { computed, ref, watch } from 'vue'
  import { useVideoForm, useGetVideoInfo } from '@/services/pages/know/useVideo'
  import { useGetGoodListByVideoId } from '@/services/pages/good/useGood'
  import { UploadFilled, Upload } from '@element-plus/icons-vue'
  import { HMessage, HMessageBox } from '@/components/common/message'
  import { Good } from './types'
  import GoodSelectModal from '@/components/business/good-select-modal/GoodSelectModal.vue'
  import VideoPreview from '@/views/return-factory/repair/form/components/custom-info/VideoPreview.vue'
  import { fileUpload } from '@/api/upload'
  import infoTip from '@/config/info-tip'

  const { form, formSaveLoading, formSave, resetForm } = useVideoForm()
  const { info, getInfoLoading, getInfo } = useGetVideoInfo()
  const {
    list: goodListByVideoId,
    getListLoading: getGoodListLoading,
    getList: getGoodList,
  } = useGetGoodListByVideoId()

  defineOptions({
    name: 'VideoFormModal',
  })

  const props = defineProps({
    videoId: {
      type: String,
      default: () => '',
    },
  })

  const emits = defineEmits<{
    (e: 'update'): void
  }>()

  // 抽屉显示状态
  const visible = defineModel('visible', { type: Boolean, default: false })

  // 表单组件实例
  const formInstance = ref<FormInstance | null>(null)

  // 验证规则
  const rules = ref({
    name: [{ required: true, message: '请输入视频名称', trigger: 'blur' }],
  })

  // 封面文件对象
  const coverFileObj = ref<{ file: UploadRawFile; url: string }>({
    file: null,
    url: '',
  })

  // 视频列表
  const videoList = ref<Array<{ file: UploadRawFile; url: string; id: string; fileName: string }>>(
    [],
  )

  // 产品列表
  const goodList = ref<Array<Good>>([])

  // 产品选择弹窗显示状态
  const goodSelectModalVisible = ref(false)

  // 初始预览视频索引
  const videoInitialIndex = ref(0)

  // 视频预览地址集合
  const videoPreviewPathList = ref<Array<string>>([])

  // 视频预览弹窗显示状态
  const videoPreviewModalVisible = ref(false)

  // 文件上传加载
  const fileUploadLoading = ref(false)

  // 加载
  const loading = computed(() => {
    return (
      formSaveLoading.value ||
      fileUploadLoading.value ||
      getInfoLoading.value ||
      getGoodListLoading.value
    )
  })

  /**
   * 隐藏抽屉
   */
  const hideDrawer = () => {
    resetForm()
    visible.value = false
    videoList.value.length = 0
    coverFileObj.value = {
      file: null,
      url: '',
    }
  }

  /**
   * 封面上传事件
   * @param {UploadFile} file - 文件对象
   */
  const handleUploadCover = (file: UploadFile) => {
    if (!file.raw.type.includes('image')) {
      HMessageBox.error('只能上传图片')
      return
    }
    if (file.raw.size / 1024 / 1024 > 50) {
      HMessageBox.error('图片大小不能超过50MB！')
      return
    }
    coverFileObj.value = {
      file: file.raw,
      url: URL.createObjectURL(file.raw),
    }
  }

  /**
   * 封面删除事件
   */
  const onDelCover = () => {
    coverFileObj.value = {
      file: null,
      url: '',
    }
    form.value.image = ''
  }

  /**
   * 视频上传
   * @param {UploadFile} file - 文件对象
   */
  const handleUploadVideo = (file: UploadFile) => {
    if (!file.name.endsWith('mp4')) {
      HMessageBox.error('只能上传MP4文件！')
      return
    }

    if (file.size / 1024 / 1024 > 20) {
      HMessageBox.error('视频大小不能超过20MB！')
      return
    }

    if (videoList.value.length >= 20) {
      HMessageBox.error('最多上传20个视频！')
      return
    }

    videoList.value.push({
      file: file.raw,
      url: URL.createObjectURL(file.raw),
      id: '',
      fileName: file.name,
    })
  }

  /**
   * 工单列表初始化
   */
  const goodListInit = () => {
    goodList.value = [
      {
        brand: '',
        brandId: null,
        code: '',
        createTime: null,
        goodsType: 1,
        id: '',
        itemNumber: null,
        model: '',
        name: '',
        source: null,
        specName: null,
        status: null,
        type: '',
        typeThree: '',
        typeTwo: '',
        unit: null,
        updateTime: null,
        warrantyDay: null,
        isFixed: true,
      },
    ]
  }

  /**
   * 产品选择事件
   * @param {Array<NotSpecGoodListItem>} goods - 产品列表
   */
  const handleGoodSelect = (goods: Array<NotSpecGoodListItem>) => {
    goodListInit()
    goods.forEach((good) => {
      goodList.value.push({
        ...good,
        isFixed: false,
      })
    })
  }

  /**
   * 封面上传
   */
  const coverUpload = async () => {
    if (coverFileObj.value.file) {
      const files = [coverFileObj.value.file]
      fileUploadLoading.value = true
      const res = await fileUpload(files)
      fileUploadLoading.value = false
      return res.data.data.rows[0]
    }
    return ''
  }

  /**
   * 视频上传
   */
  const videoUpload = async () => {
    const fileList = videoList.value.filter((item) => !!item.file).map((item) => item.file)
    if (fileList.length > 0) {
      fileUploadLoading.value = true
      const res = await fileUpload(fileList)
      fileUploadLoading.value = false
      return res.data.data.rows
    }
    return []
  }

  /**
   * 确定事件
   */
  const onConfirm = async () => {
    if (formInstance.value) {
      try {
        await formInstance.value.validate()
        const coverUrl = await coverUpload()
        if (coverUrl) {
          form.value.image = coverUrl
        }
        const videoUrls = await videoUpload()
        if (videoUrls.length > 0) {
          videoUrls.forEach((path) => {
            form.value.videoPaths.push({
              id: '',
              path,
            })
          })
        }
        form.value.videoGoodsRelationVos = goodList.value.slice(1).map((item) => {
          return {
            goodsId: item.id,
            type: item.goodsType,
          }
        })
        const res = await formSave()
        if (res.code === 20000) {
          HMessage.success(props.videoId ? '编辑成功' : '创建成功')
          hideDrawer()
          emits('update')
          return
        }
        HMessageBox.error(infoTip.know.video.err_code[res.code] || res.message)
      } catch (error) {
        // error
      }
    }
  }

  /**
   * 视频删除事件
   */
  const handleDelVideo = (index: number) => {
    const video = videoList.value.splice(index, 1)[0]
    if (video.id) {
      form.value.delVideoPaths.push({
        id: video.id,
        path: video.url,
      })
    }
  }

  /**
   * 视频预览事件
   * @param {Number} index - 预览视频索引
   */
  const handleVideoPreview = (index: number) => {
    videoInitialIndex.value = index
    videoPreviewModalVisible.value = true
    videoPreviewPathList.value = videoList.value.map((video) => video.url)
  }

  /**
   * 获取表格行类名
   * @param {Object} data - 行数据
   * @param {Good} data.row - 产品对象
   * @param {Number} data.rowIndex - 行索引
   */
  const getRowClassName = (data: { row: Good; rowIndex: number }) => {
    if (data.rowIndex === 0) {
      return 'fixed-row'
    }
  }

  /**
   * 产品删除事件
   * @param {Number} index - 产品索引
   */
  const handleGoodDel = (index: number) => {
    goodList.value.splice(index, 1)
  }

  watch(
    visible,
    async (value) => {
      if (value) {
        goodListInit()

        if (props.videoId) {
          await getGoodList(props.videoId)
          await getInfo(props.videoId)
          goodListByVideoId.value.forEach((item) => {
            goodList.value.push({
              isFixed: false,
              brand: '',
              brandId: '',
              code: item.goodsCode,
              id: item.goodsId,
              model: item.goodsModel,
              name: item.goodsName,
              goodsType: item.type,
              createTime: '',
              itemNumber: 0,
              source: 1,
              specName: '',
              status: 1,
              type: '',
              typeThree: '',
              typeTwo: '',
              unit: '',
              updateTime: '',
              warrantyDay: '',
            })
          })
          form.value.id = info.value.id
          form.value.image = info.value.image
          form.value.name = info.value.name
          form.value.status = info.value.status
          form.value.videoGoodsRelationVos = info.value.videoGoodsRelationVos
          form.value.videoPaths = info.value.videoPaths
          form.value.visibilityType = info.value.visibilityType
          videoList.value = form.value.videoPaths.map((item) => {
            const fileName = item.path.split('/').at(-1).split('.')[0]
            return {
              file: null,
              url: item.path,
              id: item.id,
              fileName,
            }
          })
          coverFileObj.value = {
            file: null,
            url: info.value.image,
          }
        }
      }
    },
    { immediate: true },
  )
</script>

<template>
  <h-drawer
    v-model="visible"
    :title="props.videoId ? '编辑视频' : '创建视频'"
    :width="900"
    unit="px"
    :loading="loading"
    @close="hideDrawer"
  >
    <el-form
      ref="formInstance"
      label-position="top"
      inline-message
      class="modal_form_content"
      :rules="rules"
      :model="form"
      scroll-to-error
      :scroll-into-view-options="{ behavior: 'smooth' }"
    >
      <!-- 视频名称 -->
      <el-form-item label="视频名称" prop="name">
        <el-input v-model.trim="form.name" placeholder="请输入视频名称" maxlength="20" />
      </el-form-item>

      <!-- 可见类型 -->
      <el-form-item label="可见类型" prop="visibilityType">
        <el-select v-model="form.visibilityType" placeholder="请选择可见类型">
          <el-option :value="1" label="全部可见"></el-option>
          <el-option :value="2" label="网点可见"></el-option>
          <el-option :value="3" label="公司可见"></el-option>
        </el-select>
      </el-form-item>

      <!-- 状态 -->
      <el-form-item label="状态" prop="status" class="same_line">
        <el-radio-group v-model="form.status">
          <el-radio :value="false" size="small">启用</el-radio>
          <el-radio :value="true" size="small">禁用</el-radio>
        </el-radio-group>
      </el-form-item>

      <!-- 封面 -->
      <el-form-item label="封面" prop="image">
        <el-upload
          v-if="!coverFileObj.url"
          :auto-upload="false"
          :show-file-list="false"
          accept="image/*"
          class="cover"
          :on-change="handleUploadCover"
        >
          <el-icon :size="24" color="#007cff">
            <UploadFilled />
          </el-icon>
        </el-upload>
        <h-image
          v-else
          :src="coverFileObj.url"
          :width="70"
          :height="43.75"
          :padding="2"
          @del="onDelCover"
        ></h-image>
      </el-form-item>

      <!-- 视频列表 -->
      <el-form-item label="视频列表" prop="videoPaths">
        <el-upload
          multiple
          accept=".mp4"
          :auto-upload="false"
          :show-file-list="false"
          :on-change="handleUploadVideo"
        >
          <h-plain-button :disabled="videoList.length >= 20">
            <el-icon>
              <Upload />
            </el-icon>
            点击上传视频
          </h-plain-button>
        </el-upload>
        <div class="video-list">
          <div v-for="(video, videoIndex) in videoList" :key="videoIndex" class="video">
            <h-tooltip-text :text="video.fileName" :max-width="100" :height="16"></h-tooltip-text>
            <h-link :height="16" @click="handleVideoPreview(videoIndex)">预览</h-link>
            <h-link :height="16" type="error" @click="handleDelVideo(videoIndex)">删除</h-link>
          </div>
        </div>
      </el-form-item>

      <!-- 产品列表 -->
      <el-form-item label="产品列表" prop="videoGoodsRelationVos">
        <el-table
          :data="goodList"
          :border="true"
          stripe
          max-height="400"
          :row-class-name="getRowClassName"
        >
          <!-- 序号 -->
          <el-table-column fixed="left" :align="'center'" width="50" label="序号">
            <template #default="{ row, $index }">
              {{ row.isFixed ? '' : $index }}
            </template>
          </el-table-column>

          <!-- 产品名称 -->
          <el-table-column
            prop="name"
            label="产品名称"
            min-width="140"
            show-overflow-tooltip
          ></el-table-column>

          <!-- 产品编号 -->
          <el-table-column
            prop="code"
            label="产品编号"
            width="140"
            show-overflow-tooltip
          ></el-table-column>

          <!-- 产品型号 -->
          <el-table-column
            prop="model"
            label="产品型号"
            width="140"
            show-overflow-tooltip
          ></el-table-column>

          <!-- 操作 -->
          <el-table-column label="操作" fixed="right">
            <template #default="{ row, $index }">
              <h-link v-if="row.isFixed" @click="goodSelectModalVisible = true">添加产品</h-link>
              <h-link v-else type="error" @click="handleGoodDel($index)">删除</h-link>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
    </el-form>
    <template #footer>
      <h-button is-modal type="primary" @click="onConfirm">确定</h-button>
      <h-button is-modal @click="hideDrawer">取消</h-button>
    </template>

    <good-select-modal
      v-model:visible="goodSelectModalVisible"
      :good-select-list="goodList.slice(1)"
      @select-good="handleGoodSelect"
    ></good-select-modal>

    <video-preview
      v-model:visible="videoPreviewModalVisible"
      :initial-index="videoInitialIndex"
      :video-list="videoPreviewPathList"
    ></video-preview>
  </h-drawer>
</template>

<style scoped lang="scss">
  .el-form {
    height: 100%;
    overflow: auto;
  }

  :deep(.fixed-row) {
    position: sticky;
    position: -webkit-sticky;
    top: 0;
    z-index: 3;
  }

  .cover {
    width: 70px;
    height: 43.75px;
    border: 1px solid #dcdfe6;

    :deep(.el-upload) {
      width: 100%;
      height: 100%;
    }
  }

  .video-list {
    width: 100%;
    display: grid;
    grid-template-columns: repeat(3, 163px);
    justify-content: space-between;
    row-gap: 5px;
    margin-top: 5px;

    .video {
      display: flex;
      column-gap: 5px;
      height: 16px;
    }
  }
</style>
